package cn.jbolt.ai.core.chain.node.action.apicall;

import cn.jbolt.ai.core.chain.ChainContext;
import cn.jbolt.ai.core.chain.node.base.AppConfigConstant;
import cn.jbolt.ai.core.chain.node.base.LlmConfig;
import cn.jbolt.ai.core.chain.node.base.BaseNode;
import cn.jbolt.ai.core.chain.node.provider.CommonNodeProvider;
import cn.jbolt.util.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.jboltai.util.http.HttpMethod;
import com.jboltai.util.http.HttpUtil;
import com.jboltai.util.http.RequestInstance;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Iterator;


@Component
public class ApiCallNodeProvider extends BaseNode implements CommonNodeProvider {

    private static final Logger logger = LoggerFactory.getLogger(ApiCallNodeProvider.class);

    public void provide(JsonNode nodeConfig, ChainContext context) {
        // 解析API调用配置
        JsonNode apiCallConfigNode = nodeConfig.get(AppConfigConstant.CONFIG_TYPE_API_CALL);
        ApiCallConfig apiCallConfig = ApiCallConfig.from(apiCallConfigNode);

        if (apiCallConfig.getUrl() == null || apiCallConfig.getUrl().isEmpty()) {
            logger.error("API调用URL不能为空");
            throw new IllegalArgumentException("API调用URL不能为空");
        }

        String url = replaceArgs(apiCallConfig.getUrl(), context.getArgs());

        // 创建请求实例
        RequestInstance requestInstance;
        if (apiCallConfig.getMethod() == HttpMethod.GET) {
            requestInstance = HttpUtil.get(url);
        } else if (apiCallConfig.getMethod() == HttpMethod.POST) {
            requestInstance = HttpUtil.post(url);
        } else {
            logger.error("不支持的HTTP方法: {}", apiCallConfig.getMethod());
            throw new IllegalArgumentException("不支持的HTTP方法: " + apiCallConfig.getMethod());
        }

        // 添加请求头
        if (apiCallConfig.getHeaders() != null) {
            Iterator<JsonNode> headers = apiCallConfig.getHeaders().elements();
            while (headers.hasNext()) {
                JsonNode header = headers.next();
                String key = header.get("key").asText();
                String value = replaceArgs(header.get("value").asText(), context.getArgs());
                if (!key.isEmpty()) {
                    requestInstance.addHeader(key, value);
                }
            }
        }

        // 添加查询参数
        if (apiCallConfig.getQueryParams() != null) {
            Iterator<JsonNode> params = apiCallConfig.getQueryParams().elements();
            while (params.hasNext()) {
                JsonNode param = params.next();
                String key = param.get("key").asText();
                String value = replaceArgs(param.get("value").asText(), context.getArgs());
                if (!key.isEmpty()) {
                    requestInstance.addQueryParam(key, value);
                }
            }
        }

        // 处理POST请求的请求体
        if (apiCallConfig.getMethod() == HttpMethod.POST) {
            String bodyType = apiCallConfig.getBodyType();

            if ("json".equals(bodyType)) {
                // 处理JSON请求体
                requestInstance.setContentTypeToJson();
                requestInstance.setBody(replaceArgs(apiCallConfig.getJsonBody(), context.getArgs()), "application/json");
            } else if ("form".equals(bodyType)) {
                // 处理表单请求体
                requestInstance.setContentTypeToForm();
                if (apiCallConfig.getFormParams() != null) {
                    Iterator<JsonNode> params = apiCallConfig.getFormParams().elements();
                    while (params.hasNext()) {
                        JsonNode param = params.next();
                        String key = param.get("key").asText();
                        String value = replaceArgs(param.get("value").asText(), context.getArgs());
                        if (!key.isEmpty()) {
                            requestInstance.addFormParam(key, value);
                        }
                    }
                }
            } else if ("raw".equals(bodyType)) {
                // 处理原始请求体
                String rawBody = replaceArgs(apiCallConfig.getRawBody(), context.getArgs());
                requestInstance.setBody(rawBody, "text/plain");
            }
        }

        // 执行请求并获取响应
        try (Response response = requestInstance.sendForResponse()) {
            if (!response.isSuccessful()) {
                logger.error("API调用失败，状态码: {}", response.code());
                throw new RuntimeException("API调用失败，状态码: " + response.code() +"\n响应内容：" + response.toString());
            }

            // 处理响应
            try (ResponseBody responseBody = response.body()) {
                if (responseBody == null) {
                    logger.error("API调用返回空响应体");
                    throw new RuntimeException("API调用返回空响应体 ");
                }

                String responseString = responseBody.string();
                Object result;

                // 根据响应类型解析响应
                if ("json".equals(apiCallConfig.getResponseType().name().toLowerCase())) {
                    try {
                        result = JSONUtil.MAPPER.readTree(responseString);
                    } catch (Exception e) {
                        logger.error("JSON响应解析失败: {}", responseString, e);
                        throw new RuntimeException("JSON响应解析失败: " + responseString);
                    }
                } else {
                    // 默认为文本
                    result = responseString;
                }

                // 将结果存储在上下文中
                String outputField = apiCallConfig.getOutputField();
                if (outputField != null && !outputField.isEmpty()) {
                    context.setAttr(outputField, result);
                    logger.debug("API调用成功，结果存储在字段: {}", outputField);
                }
            }
        } catch (Exception e) {
            logger.error("ApiCall发生异常", e);
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            } else {
                throw new RuntimeException(e);
            }
        }
    }



}
